2023/12/234396字符

设计模式

创建型模式

工厂模式

  • 提供一种集中化、统一管理的方式,避免了分散创建对象导致的代码重复、灵活性差的问题。(类、构造函数式写法)

单例模式

  • 保证一个类仅有一个实例,并提供一个访问他的全局访问点(jQuery)
let Test = (function () {
    let instance;
    return function (name) {
        if (typeof instance === 'object') return instance;
        instance = this;
        this.name = name;
    }
})()

let a = new Test();
Test.prototype.lastName = 'y';
let b = new Test();
console.log(a == b, a.lastName, b.lastName);  //--> true "y" "y"
const getSingle = function (func) {
    let result;
    return function () {
        if (!result) {
            result = func.apply(this, arguments);
        }
        return result;
    }
}
/**
 * 包装单例类
 */
function singleton(className) {
    let ins;
    return new Proxy(className, {
        construct(target, args) {
            if (!ins) {
                ins = new target(...args);
            }
            return ins;
        }
    })
}

class Video {
    construct() {}
}
const v = singleton(Video);
v.prototype.a = 111;
console.log(new Video().a)

结构型模式

代理模式

  • 为一个对象提供一种代理控制对这个对象的访问(Vue3 ref 对象,ES6 生成器)
    • 增加对一个对象的访问控制;
    • 访问一个对象的过程中需要增加额外的逻辑。

外观模式

  • 子系统中的一组接口提供一个统一的高层接口,使子系统更加容易使用。(封装过的 DOM 操作、事件,兼容各个版本浏览器)

行为型模式

策略模式

  • 对象有某个行为,但是在不同场景下,该行为有不同的实现算法。(TS 装饰器)
    • 方便运行时切换算法和策略;
    • 代码更简洁,避免使用大量的条件判断;
    • 关注分离,功能之间相互分离。

迭代器模式

  • 使用可迭代式数据结构(Array、Set、Map),迭代器的接口都应该是一样的,都需遵循迭代器协议。
    • 提供一致的遍历各种数据结构的方式,而不用改变数据的内部结构;
    • 提供便利容器(集合)的的能力而无须改变容器的接口。
function Range (start, end) {
    return {
        [Symbol.iterator]: function () {
            return {
                next () {
                    if (start < end) {
                        return { value: start ++, done: false }
                    }
                    return { done: true, value: end }
                }
            }
        }
    }
}

for (num of Range(1, 5)) {
    console.log(num);
}
//--> 1, 2, 3, 4

观察者模式(发布订阅模式)

  • 被观察对象状态改变时,通过某个方法通知到观察者。(websocket、二叉树的比较、Vue 监控 DOM 树 diff 算法)
// 发布订阅模式
class EventEmitter extends EventTarget {
  on = this.addEventListener;
  off = this.removeEventListener;
  emit = (type, data) => this.dispatchEvent(new CustomEvent(type, { detail: data }));
  once = (type, callback) => this.on(type, callback, { once: true, capture: true });
}

var emitter = new EventEmitter();
function onEventX(ev) {
  console.log("event-x 收到数据:", ev.detail);
}
function onEventOnce(ev) {
  console.log("event-once 收到数据:", ev.detail);
}

// 订阅(观察者)
emitter.on("event-x", onEventX);
emitter.once("event-once", onEventOnce);

// 发布
emitter.emit("event-once", { uid: -100, message: "you love me" });
emitter.emit("event-once", { uid: -100, message: "you love me" });

emitter.emit("event-x", { uid: 100, message: "i love you" });
emitter.off("event-x", onEventX);
emitter.emit("event-x", { uid: 100, message: "i love you" });

中介者模式

  • 包装了一系列相互作用的方式,使这些对象不必直接相互作用,而是中介者协调他们之间的交互,从而使他们松散偶合。(Vue 中的 this 调用)

访问者模式

  • 算法与对象结构分离,访问者能让我们在不改变数据结构的前提下给该对象增加新的逻辑。(纯函数)